import { Engine } from '@babylonjs/core/Engines/engine';
import { Stage } from '../../base/stage';
import { CreateUINode, UINode } from '../../gui/base/ui-node';
import { CreateDevelopmentUiNodes } from './ui-development';
import { IUIContainerOptions, UIContainer } from '../../gui/base/ui-container';
import { UIRootTool } from './ui-root-tool';
import { Quaternion, Vector3 } from '@babylonjs/core/Maths/math.vector';
import { DEGREE } from '../../tool/calculation';
import { CreateUIButton } from '../../gui/control/ui-button';
import { ANCHOR, AbstractBase } from '../../gui/control/abstract-base';
import { ResetStageImage } from '../../texture/icon-image/reset-stage-image';
import { ResetSightImage } from '../../texture/icon-image/reset-sight-image';
import { ImmersiveImage } from '../../texture/icon-image/immersive-image';
import { ControllerImage } from '../../texture/icon-image/controller-image';
import { CreateUIGroup } from '../../gui/control/ui-group';
import { CreateUIKeyboard, UIKeyboard } from '../../gui/control/ui-keyboard';
import { WebXRCamera } from '@babylonjs/core/XR/webXRCamera';
import { Helper } from '../../tool/helper';
import { BabylonContainer } from '../../base/babylon-container';
import { CreateUIRectangle } from '../../gui/control/ui-rectangle';
import { CreateUIText } from '../../gui/control/ui-text';
import { Control } from '@babylonjs/gui/2D/controls/control';
import { XRStage } from '../../base/xr-stage';
import { Scene } from '@babylonjs/core/scene';
import { Camera } from '@babylonjs/core/Cameras/camera';
import { OperationGuide } from './operation-guide/operation-guide';
import { OperationGuideType } from './operation-guide/operation-guide-type';


/**
 * 工具类工程ui容器模板的参数对象
 * @param isProduction 是否为正式产品（正式产品会禁用一部分ui组件）
 * @param isOriginalQr 是否使用原始页面的二维码（原始页面：index-original.html）
 * @param qrCodeSize 二维码大小
 * @param appName 工程名称
 * @param lineHeight 行高
 * @param alpha 透明度
 * @param fontSize 字体大小
 * @param cornerRadius 圆角半径
 * @param gridBorderThickness 选中时的边框厚度
 * @param spacing 选项卡之间的间隔
 * @param useKeyboard 是否使用软键盘
 * @param keyboardWidth 软键盘宽度
 * @param keyboardHeight 软键盘高度
 * @param xrRatio 沉浸模式下的界面比例
 * @param topRenderingId 最上层ui的渲染顺序值
 * @param frontRenderingId 前层ui渲染顺序值
 * @param backRenderingId 后层ui渲染顺序值
 * @param useXR 是否使用xr内容
 * @param useDefaultXRBoot 是否使用默认的xr引导
 * @param useDefaultXRBootOnlySupported 只在支持时使用默认的xr引导
 * @param useOperationGuide 是否启用操作指导
 * @param operationGuideTypes 操作指导面板包含的指导类型
 * @param useResetStage 是否使用重置舞台按钮
 * @param useResetSight 是否使用重设视角按钮
 */
interface IUIContainerToolOptions extends IUIContainerOptions {
    isProduction?: boolean,
    isOriginalQr?: boolean,
    qrCodeSize?: number,
    appName?: string,
    lineHeight?: number,
    alpha?: number,
    fontSize?: number,
    cornerRadius?: number,
    gridBorderThickness?: number,
    spacing?: number,
    useKeyboard?: boolean,
    keyboardWidth?: number,
    keyboardHeight?: number,
    xrRatio?: { x: number, y: number },
    topRenderingId?: number,
    frontRenderingId?: number,
    backRenderingId?: number,
    useXR?: boolean,
    useDefaultXRBoot?: boolean,
    useDefaultXRBootOnlySupported?: boolean,
    useOperationGuide?: boolean,
    operationGuideTypes?: Array<OperationGuideType>,
    useResetStage?: boolean,
    useResetSight?: boolean,
}


/**
 * 工具类工程ui容器模板
 * @param engine 引擎
 * @param stage 所在舞台
 * @param root ui根容器
 * @param options 参数对象
 */
class UIContainerTool extends UIContainer {

    private _camera: Camera | null = null;

    protected keyboard!: UIKeyboard;
    protected keyboardNode!: UINode;
    protected leftBottomNode!: UINode;
    protected rightBottomNode!: UINode;
    protected bootImmersive!: UINode;

    constructor(engine: Engine, stage: Stage, root: UIRootTool, options?: IUIContainerToolOptions) {
        super(engine, stage, root, options);
        stage.uiScene.onActiveCameraChanged.add((scene: Scene) => {
            if (!Helper.isCameraGeneral(scene.activeCamera)) return;
            if (this._camera && this._camera.uniqueId === scene.activeCamera?.uniqueId) return;
            this._camera = scene.activeCamera;
            this.onImmersive(scene.activeCamera instanceof WebXRCamera);
        });
    }

    /**
     * 沉浸模式变化时的响应函数
     * @param immersive 是否处于沉浸模式
     */
    protected onImmersive(immersive: boolean): void {
        const ang = BabylonContainer.isRightHand ? 25 : -25;
        if (OperationGuide.nodes) {
            OperationGuide.display = false;
            OperationGuide.nodes.forEach(node => {
                node.rotation = Quaternion.RotationAxis(Vector3.UpReadOnly, immersive ? -ang * DEGREE * 0.3 : 0);
            });
        }
    }

    protected initializeStyle(options: IUIContainerToolOptions): IUIContainerToolOptions {
        return {
            appName: options.appName || 'default',
            isOriginalQr: options.isOriginalQr || false,
            qrCodeSize: options.qrCodeSize || 512,
            isProduction: options.isProduction || false,
            lineHeight: options.lineHeight || 0.7,
            alpha: options.alpha === undefined ? 0.7 : options.alpha,
            cornerRadius: options.cornerRadius || 5,
            fontSize: options.fontSize || 22,
            gridBorderThickness: options.gridBorderThickness || 3,
            spacing: options.spacing || 0.01,
            useKeyboard: options.useKeyboard || false,
            keyboardWidth: options.keyboardWidth || 16,
            keyboardHeight: options.keyboardHeight || 8,
            xrRatio: options.xrRatio || { x: 0.6, y: 1.1 },
            frontRenderingId: options.frontRenderingId || 2,
            backRenderingId: options.backRenderingId || 1,
            topRenderingId: options.topRenderingId || 2,
            useXR: options.useXR,
            useDefaultXRBoot: options.useDefaultXRBoot,
            useDefaultXRBootOnlySupported: options.useDefaultXRBootOnlySupported,
            useOperationGuide: options.useOperationGuide,
            operationGuideTypes: options.operationGuideTypes || [OperationGuideType.move, OperationGuideType.orientate, OperationGuideType.click, OperationGuideType.drag],
            useResetStage: options.useResetStage === undefined ? true : options.useResetStage,
            useResetSight: options.useResetSight === undefined ? true : options.useResetSight,
        };
    }

    protected initializeUINodes(engine: Engine, stage: Stage, style: IUIContainerToolOptions): UINode[] {
        return [
            ...this.initializeDevelopmentNodes(engine, stage, style),
            ...this.initializeDefaultNodes(engine, stage, style),
            ...this.initializeCustomNodes(engine, stage, style),
        ];
    }

    /**
     * 初始化开发阶段ui组件（截屏、二维码）
     * @param engine 引擎
     * @param stage 舞台
     * @param style 参数对象
     * @returns ui节点集合
     */
    private initializeDevelopmentNodes(engine: Engine, stage: Stage, style: IUIContainerToolOptions): UINode[] {
        const developmentNodes = style.isProduction ? [] : CreateDevelopmentUiNodes(this.name, engine, stage, this.root as UIRootTool, style);
        return [...developmentNodes];
    }

    /**
     * 初始化默认ui节点
     * @param engine 引擎
     * @param stage 舞台
     * @param style 参数对象
     * @returns ui节点集合
     */
    private initializeDefaultNodes(engine: Engine, stage: Stage, style: IUIContainerToolOptions): UINode[] {
        const nodes: UINode[] = [];
        if (style.useKeyboard) {
            this.keyboardNode = this.initializeUiKeyboardNode(engine, stage, style);
            let c = 0;
            let tar = this.keyboardNode.getControl(c, true);
            while (tar) {
                if (tar instanceof UIKeyboard) {
                    this.keyboard = tar;
                    break;
                }
                c++;
                tar = this.keyboardNode.getControl(c, true)
            }
            nodes.push(this.keyboardNode);
        }
        nodes.push(
            this.leftBottomNode = this.initializeLeftBottomNode(engine, stage, style),
            ...this.initializeRightBottomNode(engine, stage, style),
        );

        return nodes;
    }

    /**
     * 初始化左下侧ui节点（重置按钮，设置视角按钮）
     * @param engine 引擎
     * @param stage 舞台
     * @param style 参数对象
     * @returns ui节点
     */
    private initializeLeftBottomNode(engine: Engine, stage: Stage, style: IUIContainerToolOptions): UINode {
        const node = CreateUINode(this.name + '-left-bottom-node', stage.uiScene,
            {
                key: this.name + '-left-bottom-node',
                anchor: new Vector3(0, 1, 0),
                lockToCamera: true,
                xrRatio: style.xrRatio,
                offset: new Vector3(0.01, 0.01, 0),
            },
            [
                CreateUIGroup(this.name + '-left-buttom-group', stage.uiScene,
                    {
                        anchor: ANCHOR.LEFT_BOTTOM, autoLayout: true, spacing: style.spacing, ignoreTitleLayout: true,
                        headerOptions: { width: 1, display: false }
                    },
                    this.initializeResetButtons(engine, stage, style)
                ),
            ]
        );
        return node;
    }

    /**
     * 初始化沉浸模式ui（头盔按钮及引导面板）
     * @param engine 引擎
     * @param stage 舞台
     * @param style 参数对象
     * @returns ui节点集合
     */
    private initializeRightBottomNode(engine: Engine, stage: Stage, style: IUIContainerToolOptions): UINode[] {
        if ((!style.useXR) && (!style.useOperationGuide)) return [];
        const xrAvailable = this.xrAvailable(stage, style);
        let btnStyle: any = {
            anchor: ANCHOR.RIGHT_BOTTOM,
            width: style.lineHeight,
            height: style.lineHeight,
            cornerRadius: style.cornerRadius,
            alpha: style.alpha,
            renderingGroupId: style.frontRenderingId,
        };
        this.rightBottomNode = CreateUINode(this.name + '-right-bottom-panel', stage.uiScene,
            {
                key: this.name + '-right-bottom-panel',
                anchor: new Vector3(1, 1, 0),
                lockToCamera: true,
                xrRatio: style.xrRatio,
                offset: new Vector3(-style.spacing!, style.spacing, 0),
                display: xrAvailable || style.useOperationGuide,
            },
            [
                CreateUIGroup(this.name + '-right-bottom-group', stage.uiScene,
                    {
                        anchor: ANCHOR.RIGHT_BOTTOM, autoLayout: true, spacing: style.spacing, ignoreTitleLayout: true,
                        headerOptions: { width: 1, display: false }
                    },
                    (() => {
                        const uis: AbstractBase[] = [];
                        if (xrAvailable) {
                            uis.push(
                                CreateUIButton(this.name + '-exit-immersive-button', stage.uiScene,
                                    {
                                        ...btnStyle,
                                        imageUrl: ImmersiveImage(2, '#ffffff'),
                                    },
                                    () => {
                                        if (stage instanceof XRStage) stage.changeImmersive();
                                        (this.root as UIRootTool).onImmersiveButtonClick(stage);
                                        if (this.bootImmersive) this.bootImmersive.display = false;
                                    }
                                )
                            );
                        }
                        if (style.useOperationGuide) {
                            OperationGuide.initialize(stage, style, style.operationGuideTypes!);
                            uis.push(
                                CreateUIButton(this.name + '-setting-button', stage.uiScene,
                                    {
                                        ...btnStyle,
                                        imageUrl: ControllerImage(2, '#ffffff'),
                                    },
                                    () => {
                                        if (OperationGuide.nodes) OperationGuide.display = !OperationGuide.display;
                                        (this.root as UIRootTool).onOperationGuideButtonClick(stage);
                                    }
                                ),
                            );
                        }
                        return uis;
                    })()
                ),
            ]
        );
        if (!style.useDefaultXRBoot) return OperationGuide.nodes ? [this.rightBottomNode, ...OperationGuide.nodes] : [this.rightBottomNode];

        this.bootImmersive = CreateUINode(this.name + '-boot-immersive-panel', stage.uiScene,
            {
                key: this.name + '-boot-immersive-panel',
                anchor: new Vector3(0.5, 0.5, 0),
                lockToCamera: true,
                xrRatio: style.xrRatio,
                display: style.useDefaultXRBootOnlySupported ? xrAvailable : true,
            },
            [
                CreateUIRectangle(this.name + '-boot-immersive-panel-background', stage.uiScene, {
                    anchor: ANCHOR.CENTER,
                    top: 0,
                    width: 10,
                    height: 2.3,
                    alpha: 0.9,
                    depth: 0.002,
                    cornerRadius: 10,
                    renderingGroupId: style.backRenderingId,
                }),
                CreateUIText(this.name + '-boot-immersive-panel-content', stage.uiScene, {
                    anchor: ANCHOR.CENTER_TOP,
                    text: xrAvailable ? '🔔：是否启用沉浸模式？也可在其他时间通过【点击】右\n下侧头盔按钮进入（或退出）沉浸模式。' : '🔔：当前设备不支持沉浸模式，程序将以普通模式运行，\n准备好开始了吗？',
                    fontColor: '#ffffff',
                    fontSize: 24,
                    width: 9.5,
                    height: 1.3,
                    top: 0.11,
                    renderingGroupId: style.frontRenderingId,
                    textVerticalAlignment: Control.VERTICAL_ALIGNMENT_CENTER,
                    textHorizontalAlignment: Control.HORIZONTAL_ALIGNMENT_LEFT,
                }),
                CreateUIButton(this.name + '-boot-immersive-panel-button-1', stage.uiScene,
                    btnStyle = {
                        anchor: ANCHOR.CENTER_TOP,
                        text: xrAvailable ? '现在进入' : '',
                        fontSize: 24,
                        width: 2.5,
                        height: 0.68,
                        top: -0.02,
                        left: 0.05,
                        cornerRadius: 7,
                        background: '#000099',
                        renderingGroupId: style.frontRenderingId,
                        display: xrAvailable,
                    },
                    () => {
                        if (stage instanceof XRStage) stage.changeImmersive();
                        this.bootImmersive.display = false;
                        (this.root as UIRootTool).onBootImmersiveButtonsClick(stage, true);
                    }
                ),
                CreateUIButton(this.name + '-boot-immersive-panel-button-2', stage.uiScene,
                    {
                        ...btnStyle,
                        text: xrAvailable ? '稍后再说' : '准备好了',
                        left: 0.34,
                        display: true,
                    },
                    () => {
                        if (stage instanceof XRStage) stage.changeImmersive(true);
                        this.bootImmersive.display = false;
                        (this.root as UIRootTool).onBootImmersiveButtonsClick(stage, false);
                    }
                ),
            ]
        );

        return OperationGuide.nodes ? [this.rightBottomNode, this.bootImmersive, ...OperationGuide.nodes] : [this.rightBottomNode, this.bootImmersive];
    }

    /**
     * 初始化软键盘ui节点
     * @param engine 引擎
     * @param stage 舞台
     * @param style 参数对象
     * @returns ui节点
     */
    protected initializeUiKeyboardNode(engine: Engine, stage: Stage, style: IUIContainerToolOptions): UINode {
        const node = CreateUINode(this.name + '-keyboard-panel', stage.uiScene,
            {
                lockToCamera: true,
                anchor: new Vector3(0.5, 0.5, 0),
            },
            [
                CreateUIKeyboard(this.name + '-keyboard', stage.uiScene,
                    {
                        anchor: ANCHOR.CENTER,
                        width: style.keyboardWidth,
                        height: style.keyboardHeight,
                        display: false,
                        renderingGroupId: style.topRenderingId,
                    }
                ),
            ]
        );
        return node;
    }

    /**
     * 初始化重置按钮和设置视角按钮
     * @param engine 引擎
     * @param stage 舞台
     * @param style 参数对象
     * @returns 控件集合
     */
    protected initializeResetButtons(engine: Engine, stage: Stage, style: IUIContainerToolOptions): AbstractBase[] {
        const btnStyle = {
            renderingGroupId: style.frontRenderingId,
            alpha: style.alpha,
            imageUrl: ResetStageImage(),
            cornerRadius: style.cornerRadius,
            width: style.lineHeight,
            height: style.lineHeight
        }
        const controls: AbstractBase[] = [];
        if (style.useResetStage) {
            controls.push(
                CreateUIButton(this.name + '-center-bottom-reset-stage', stage.uiScene,
                    btnStyle,
                    () => {
                        stage.reset();
                        if (this.bootImmersive) this.bootImmersive.display = this.xrAvailable(stage, style);
                        (this.root as UIRootTool).onResetStageButtonClick(stage);

                        if (OperationGuide.nodes) OperationGuide.display = false;
                        (this.root as UIRootTool).onOperationGuideButtonClick(stage);
                    }
                )
            );
        }
        if (style.useResetSight) {
            controls.push(
                CreateUIButton(this.name + '-center-bottom-reset-sight', stage.uiScene,
                    {
                        ...btnStyle,
                        imageUrl: ResetSightImage(),
                    },
                    () => {
                        stage.resetSight();
                        (this.root as UIRootTool).onResetSightButtonClick(stage);
                    }
                )
            );
        }
        return controls;
    }

    /**
     * xr是否可用
     * @param stage 舞台 
     * @param style 参数对象
     * @returns xr是否可用
     */
    protected xrAvailable(stage: Stage, style: IUIContainerToolOptions): boolean {
        const sessionMode = (stage as any).sessionMode;
        let support: boolean = false;
        if (sessionMode === 'immersive-vr') {
            support = !!Helper.isVrSupported;
        } else if (sessionMode === 'immersive-ar') {
            support = !!Helper.isArSupported;
        }

        return (!!style.useXR) && support;
    }

    /**
     * 初始化自定义ui节点
     * @param engine 引擎
     * @param stage 舞台
     * @param style 参数对象
     * @returns ui节点集合
     */
    protected initializeCustomNodes(engine: Engine, stage: Stage, style: IUIContainerToolOptions): UINode[] {
        return [];
    }

}


export { UIContainerTool };
export type { IUIContainerToolOptions };